package spectra.ee.web.node.service;

import java.sql.SQLException;
import java.util.Hashtable;
import java.util.List;
import java.util.Vector;

import org.apache.commons.collections.map.CaseInsensitiveMap;

import spectra.base.log.Logger;
import spectra.base.sql.ibatis.SqlMapperWeb;
import spectra.base.util.StringUtil;
import spectra.base.util.Util;
import spectra.ee.web.WebPublic;
import spectra.ee.web.node.model.Node;

import com.ibatis.sqlmap.client.SqlMapClient;

/**
 * 노드 관련 클래스.
 *
 * @author kmhan
 */
public class NodeServiceBase
{

    /** Logger객체. */
    private static Logger logger = Logger.getLoggerInstance(NodeServiceBase.class.getName());

    /** SqlMapClient 객체. */
    protected static SqlMapClient sqlMap = SqlMapperWeb.getSqlMapWebInstance();

    /**
    * <pre>
    * 부모아이디로 노드정보 가져오는 메소드
    * </pre>.
    *
    * @param strParentId 부모아이디.
    *
    * @return 부모아이디로 가져온 노드객체 리스트.
    */
    public List selectNodeListByParentId(String strParentId)
    {
        List list = null;
        try
        {
            list = (List)sqlMap.queryForList("Node.selectNodeListByParentId", strParentId);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return list;
    }
    
    /**
     * <pre>
     * 도메인ID로 최대 Depth를 가져오는 메소드.
     * </pre>.
     *
     * @param domainId 도메인ID.
     *
     * @return QNA에서 사용하는 노드의 최대 depth.
     *
     * @throws Exception the exception
     */
     public int selectNodeDepthByDomainId(String domainId) throws Exception
     {
         return selectNodeDepthByDomainId(domainId,"SVQNA");
     }

    /**
    * <pre>
    * 도메인ID로 최대 Depth를 가져오는 메소드.
    * </pre>.
    *
    * @param domainId 도메인ID.
    * @param serviceType 서비스 타입.
    *
    * @return QNA에서 사용하는 노드의 최대 depth.
    *
    * @throws Exception the exception
    */
    public int selectNodeDepthByDomainId(String domainId, String serviceType) throws Exception
    {
        Object result = null;
        Node node = new Node();
        node.setDomainId(domainId);
        node.setServiceType(serviceType);
        
        result = sqlMap.queryForObject("Node.selectNodeDepthByDomainId", node);
        if(result == null)
        {
            return 0;
        }
        else
        {
            return Integer.parseInt(result.toString());
        }
    }

    /**
    * <pre>
    * 노드리스트를 가져오는 메소드. json 형태로 보낸다.
    * </pre>
    *
    * @param domainId 도메인ID.
    * @param parentNodeId 부모노드ID.
    *
    * @return 부모아이디로 가져온 노드객체 리스트.
    */
    public List selectNodeList(String domainId, String parentNodeId)
    {
        List listRet = null;
        Node node = new Node();
        node.setDomainId(domainId);
        node.setParentId(parentNodeId);
        node.setServiceType("SVQNA");
        try
        {
            listRet = (List) sqlMap.queryForList("Node.selectNodeList", node);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return listRet;
    }
    
    public List selectNodeList(String domainId, String parentNodeId, String serviceType)
    {
        List listRet = null;
        Node node = new Node();
        node.setDomainId(domainId);
        node.setParentId(parentNodeId);
        node.setServiceType(serviceType);
        try
        {
            listRet = (List) sqlMap.queryForList("Node.selectNodeList", node);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return listRet;
    }

    /**
    * <pre>
    * 채팅 가능한 노드 리스트 가져오기
    * </pre>.
    *
    * @param domainId 도메인ID.
    *
    * @return 채팅 가능한 노드ID 리스트.
    */
    public List selectChatNodeList(String domainId)
    {
        List listRet = null;
        Node node = new Node();
        node.setDomainId(domainId);
        try
        {
            listRet = (List) sqlMap.queryForList("Node.selectChatNodeList", node);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return listRet;
    }
    
    /**
     * KB의 parentId로 하위 노드리스트 가져오기
     * @param domainId
     * @param parentNodeId
     * @return
     */
    public List selectKbHelperNodeListByParentId(String domainId, String parentNodeId)
    {
        List listRet = null;
        Node node = new Node();
        node.setDomainId(domainId);
        node.setParentId(parentNodeId);
        node.setServiceType(WebPublic.SERVICE_TYPE_KB);
        try
        {
            listRet = (List) sqlMap.queryForList("Node.selectNodeList", node);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return listRet;
    }
    /**
     * 부모아이디로 부터 특정 레벨까지 하위 노드리스트를 가져오는 메소드
     * 도메인 하위 2단계 까지 가져오려면 ==> selectChildNodeListToLevel('도메인아이디', 2);
     * @param parentNodeId
     * @param level
     * @param serviceType 서비스 타입
     * @return
     */
    public Hashtable selectChildNodeListToLevel(String parentNodeId, int level, String serviceType)
    {
    	Hashtable htResult = new Hashtable();
    	
    	List list = null;
        Node node = new Node();        
        node.setParentId(parentNodeId);
        node.setServiceType(serviceType);
        node.setLevel(level);
        node.setWebviewFlag(WebPublic.FLAG_Y);
        try
        {
        	list = (List) sqlMap.queryForList("Node.selectChildNodeListToLevel", node);
            if (list != null && list.size() > 0)
            {
            	for (int i=0; i<list.size(); i++)
            	{
            		CaseInsensitiveMap map = (CaseInsensitiveMap) list.get(i);
            		//int lvl = Util.str2i(map.get("lvl")+"");
            		String nodeId = (String) map.get("node_id");
            		String nodeName = (String) map.get("node_name");
            		String parentId = (String) map.get("parent_id");
            		int depth = Util.str2i(map.get("depth")+"");
            		
            		Node nodeObj = new Node();
            		nodeObj.setNodeId(nodeId);
            		nodeObj.setNodeName(nodeName);
            		nodeObj.setParentId(parentId);
            		
            		if (htResult.containsKey(parentId))
            		{
            			Vector vNodeList = (Vector) htResult.get(parentId);
            			vNodeList.add(nodeObj);
            			htResult.put(parentId, vNodeList);
            		}
            		else
            		{
            			Vector vNodeList = new Vector();
            			vNodeList.add(nodeObj);
            			htResult.put(parentId, vNodeList);
            		}
            	}
            }
        }
        catch (Exception e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return htResult;
    }
    /**
     * 부모아이디로 부터 특정 레벨까지 지식 서비스의 하위 노드리스트를 가져오는 메소드
     * 도메인 하위 2단계 까지 가져오려면 ==> selectChildNodeListToLevel('도메인아이디', 2);
     * @param parentNodeId
     * @param level
     * @return
     */
    public Hashtable selectChildNodeListToLevel(String parentNodeId, int level)
    {
    	return selectChildNodeListToLevel(parentNodeId, level, WebPublic.SERVICE_TYPE_KB);
    }
    
    /**
     * 노드아이디로 하위 노드리스트를 계층적으로 가져오는 메소드(SVKNW)
     * @param nodeId
     * @return
     */
    public List selectNodeListByNodeIdRecursive(String nodeId)
    {
        List listRet = null;
        Node node = new Node();
        node.setNodeId(nodeId);
        node.setServiceType(WebPublic.SERVICE_TYPE_KB);
        node.setWebviewFlag(WebPublic.FLAG_Y);
        try
        {
            listRet = (List) sqlMap.queryForList("Node.selectNodeListByNodeIdRecursive", node);
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return listRet;
    }
    
    /**
     * 해당 nodeId의 상위 카테고리 경로를 특정 depth하위로 가져온다.
     * @param nodeId
     * @param depth
     * @return
     */
    public String selectParentNodePathByDepth(String nodeId, int depth)
    {
    	String result = null;
        Node node = new Node();
        node.setNodeId(nodeId);
        node.setDepth(depth);
        try
        {
            result = (String) sqlMap.queryForObject("Node.selectParentNodePathByDepth", node);
            result = StringUtil.nvl(result, "");
        }
        catch (SQLException e)
        {
            logger.error(e.getMessage());
            e.printStackTrace();
        }
        return result;
    }
}
